/* em/include/em/em.h 
 * 
 * This file is part of em. 
 * 
 * em is free software: you can redistribute it and/or modify 
 * it under the terms of the GNU General Public License as published by 
 * the Free Software Foundation, either version 3 of the License, or 
 * (at your option) any later version. 
 * 
 * em is distributed in the hope that it will be useful, 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 * GNU General Public License for more details. 
 * 
 * You should have received a copy of the GNU General Public License 
 * along with em. If not, see <https://www.gnu.org/licenses/>
 */ 




#ifndef __EM_EM_H
#define __EM_EM_H

#include <string.h>
#include <klist.h>

extern struct klist_node words;

int scan(char *s, int size);
int check_macros(void);
int expand(void);

/* can't be '\n' etc */
#define SPLIT 			';'

#define WORD_INVAL 		0
#define WORD_STR 		1
#define WORD_NAME 		2
#define WORD_DIGIT 		3
#define WORD_SPACE 		4
#define WORD_OP 		5

struct word {
	char 			*p;
	int 			len;
	int 			type;
	int 			marked;
	struct klist_node 	node;
};

#define OUTPUT_STRP 		1
#define OUTPUT_WORD 		2

struct output_tp {
	int 			type;
	union {
		char 		*p;
		struct word 	*word;
	};

	struct klist_node 	node;
};


/* greater than */
#define MPATTERN_GT 		1
/* below */
#define MPATTERN_BL 		2
/* equal. XXX: this is not usable without ';' */
#define MPATTERN_EQU 		3
/* any value allows */
#define MPATTERN_ANY 		4

struct mpattern {
	int 			dir;
	int 			nr;

	/* same as WORD_* */
	int 			type;
};

struct macro {
	/* strdup, zero terminated */
	char 			*name;
	int 			len;
#define MACRO_PATT_LEFT 	0
#define MACRO_PATT_RIGHT 	1
	struct mpattern 	patterns[2];
	struct word 		*body;
	int 			body_len;
	struct klist_node 	node;
};


#define tobool(c) 	(!!(c))
#define likely(c) 	__builtin_expect(tobool(c), 1)
#define unlikely(c) 	__builtin_expect(tobool(c), 0)


int builtin(struct word *);
long getnumber(struct word *);
struct word *word_of(struct klist_node *);
int output_remove(struct word *w);
int output(struct word *);
int outputs(char *);

static inline void mark_word(struct word *w) {
	w->marked = 1;
}

#endif

